<?php

/**
 * \file
 * Classe `EntityCollection`.
 */

/**
 * Gestion de collections d'entités chargées à la volées.
 */
namespace pilar\EntityCollections /* \cond */ ; /* \endcond */
{

/**
 * Collection d'entités.
 *
 * \todo Renommer la classe en "Collection".
 *
 * \since 10/08/2008
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
class EntityCollection extends \object implements \IteratorAggregate {
 
/**
 * Dictionnaire des entités chargées.
 */
public $_loadedEntities;


protected function loadDefaultParams() {
 parent::loadDefaultParams();
 
 $this->params->define(array(
  'directory' => DOCUMENT_ROOT.'/entities', // Dossier de base où on va chercher
                                            // les classes des entités.
  'baseNamespace' => '\\entities',   // Espace de noms où on va chercher les
                                     // classes des entités.
  'prefixes' => ''       // Préfixe à utiliser pour les tables des entités.
 ));
}


protected function initialize() {
 parent::initialize();

 $this->_loadedEntities = array();
}


/**
 * Charge une entité dans la collection à partir de son fichier de définition.
 * Si celle-ci existe déjà alors elle est remplacée. Le nom du fichier doit
 * également être le nom de l'entité passé en paramètre.
 * \param $name Nom de l'entité.
 */
private function load($name) {
 /**
  * TODO
  * Vérifier l'existence du fichier de définition de l'entité avant de le
  * charger ?
  */

 // Instanciation de la nouvelle application :
  $className = $this->get('baseNamespace').'\\'.$name;
  $entity = new $className();

  // Ajout de l'entité à la collection :
   $this->_loadedEntities[$name] = $entity;

  // Appel à la chaine d'initialisation :
   $entity->loadAdditionalMembers();

 // Application du préfixe de table si nécessaire :
  if($this->get('prefixes') != '')
   $entity->set(array(
    'prefix' => $this->get('prefixes')
   ));
}


/**
 * Accède à une entité par son nom. Si nécessaire l'entité est chargée
 * dynamiquement.
 * \param $name Nom de l'entité.
 * \return Entité recherchée.
 */
public function byName($name) {
 // Si nécessaire on charge la définition de l'entité en mémoire.
  if(!isset($this->_loadedEntities[$name])) $this->load($name);
  
 return $this->_loadedEntities[$name];
}


/**
 * Permet implicitement d'accéder à une entité par son nom avec un syntaxe
 * plus légère.
 *
 * Exemple :
 *   $this->club
 *  est équivalent à
 *   $this->byName('club')
 *
 * \param $name Nom de l'entité.
 * \return Entitée demandée.
 */
public function __get($name) {
 return $this->byName($name);
}


/**
 * Charge toutes les entités disponibles.
 *
 * \since 01/10/2008
 */
private function loadAll() {
 // On recherche tous les fichiers pouvant être des entités et on les charge :
  foreach(glob($this->get('directory').'/*.class.php') as $fileName) {
   // A partir du chemin d'accès complet du fichier on extrait le nom
   // de l'entité correspondante :
    $entityName = basename($fileName, '.class.php');
   // Enfin on force le chargement de l'entité en mémoire :
    $this->byName($entityName);
  }
}


public function getIterator() {
 // On force le chargement de toutes les entités (puisqu'on les veut toutes).
  $this->loadAll();
 
 // On retourne un iterateur maison :
  return new \ArrayIterator($this->_loadedEntities);
}

} // Class.

} // Namespace.

?>
